#include "string.h"

// 这里将复现代码包在一个命名空间域里面实现互通
// 声明和定义分离,一般缺省参数都是在声明里面标注

namespace gojo
{

// 迭代器的定义

    string::iterator string::begin ()
    {

        return _str ;

    }

    string::string::iterator string::end ()
    {

        return _str + _size ;

    }

    string::const_iterator string::begin () const
    {

        return _str ;

    }

    string::const_iterator string::end () const
    {

        return _str + _size ;

    }


// 默认函数

    // 构造函数

    string::string (const char* str) 
        : _size (strlen (str)) // 这里使用初始化表,减少strlen ()函数二点使用次数,多次使用影响性能
    {

        _capacity = _size ;

        _str = new char [_size + 1] ;

        memcpy (_str , str , _size + 1) ; // 这里的加一是为了将'\0'拷贝进来

        // cout << "string ()" << endl ;

    }

    // 拷贝构造

    // 调用拷贝构造,有两种写法: 传统写法,现代写法  两者之间的效率上没有任何差别,但是写法简洁性上面现代写法更好
    // 这里的传参为引用传参,优化减少拷贝

    // 传统写法

    // string::string (const string& str)
    // {

    //     _str = new char [str._capacity + 1] ;

    //     memcpy (_str , str._str , str._size + 1) ;

    //     _size = str._size ;

    //     _capacity = str._capacity ;

    //     cout << "string (const string& str)" << endl ;

    // }

    // 现代写法

    string::string (const string& str)
    {

        string tmp (str._str) ;

        swap (tmp) ;

        // cout << "string (const string& str)" << endl ;

    }

    // 拷贝构造

    string::~string ()
    {

        delete [] _str ;

        _str = nullptr ; // 这里也要置空防止出现野指针

        _size = _capacity = 0 ;

        // cout << "~string ()" << endl ;

    }


// 增

    // 尾插字符

    void string::push_back (char ch)
    {

        if (_size == _capacity)
        {
            
            size_t newcapacity = _capacity == 0 ? 4 : 2 * _capacity ;

            reserve (newcapacity) ;

        }

        _str [_size] = ch ;

        _size++ ;

        _str [_size] = '\0' ;
        
    }

    // 尾插字符串

    void string::append (const char* ch)
    {

        size_t len = strlen (ch) ;

        if (_size + len > _capacity)
        {

            size_t newcapacity = 2 * _capacity > _size + len ? 2 * _capacity : _size + len ;

            reserve (newcapacity) ;

        }

        memcpy (_str + _size , ch , len + 1) ;

        _size += len ;

    }

    // +=运算符的重载

    string& string::operator+= (char ch)
    {

        push_back (ch) ; // 最简单的也就是函数复用

        return *this ;

    }

    string& string::operator+= (const char* str)
    {

        append (str) ;

        return *this ;

    }

    // 任意位置插入函数
    // 注意!使用此函数的性能占用非常大,所以能不用尽量不用

    string& string::insert (size_t pos , char ch)
    {

        assert (pos < _size) ;

        if (_size == _capacity)
        {

            size_t newcapaciy = _capacity > 0 ? 4 : 2 * _capacity ;

            reserve (newcapaciy) ;

        }

        // 挪动数据
        // 但是,这里有一些内容需要注意
        // 由于使用的是size_t的类型,所以要注意防止循环挪动数据的时候出现越界,导致死循环,所以这里要特殊设计循环的结构,防止pos为0的时候出错

        for (size_t end = _size + 1 ; end > pos ; end--) // 这样子就可以防止出现死循环
        {

            _str [end] = _str [end - 1] ;

        }

        _str [pos] = ch ;

        _size++ ;

        return *this ;

    }

    string& string::insert (size_t pos , const char* str)
    {

        assert (pos < _capacity) ;

        size_t len = strlen (str) ;

        if (_size + len > _capacity)
        {

            size_t newcapacity = 2 * _capacity > _size + len ? 2 * _capacity : _size + len ;

            reserve (newcapacity) ;

        }

        for (size_t end = _size + len ; end >= pos + len ; end--)
        {

            _str [end] = _str [end - len] ;

        }

        memcpy (_str + pos , str , len) ;

        return *this ;

    }


// 删

    // 尾删字符

    void string::pop_back ()
    {

        assert (_size > 0) ;

        _size-- ;

        _str [_size] = '\0' ;

    }

    // 删除任意位置的内容

    string& string::erase (size_t pos , size_t len)
    {

        assert (pos < _size) ;

        // 要删除的数据,大于pos后面的数据个数
        // pos后面全删

        if (len == npos || len >= (_size - pos))
        {

            _size = pos ;

            _str [_size] = '\0' ;

        }

        else
        {

            size_t i = pos + len ;

            memmove (_str + pos , _str + i , _size + 1 - i) ;

            _size -= len ;

        }

        return *this ;

    }

    // 清除所有内容

    void string::clear ()
    {

        _size = 0 ;

        _str [_size] = '\0' ;

    }


// 改

    // 扩容函数

    void string::reserve (size_t n)
    {

        if (n > _capacity)
        {

            char* tmp = new char [n + 1] ;

            memcpy (tmp , _str , _size + 1) ;

            delete [] _str ;

            _str = tmp ;

            _capacity = n ;

        }

    }

    // 赋值运算符重载

    // 传统写法 s1 = s2

    // string& string::operator= (const string& s)
    // {

    //     if (this != &s)
    //     {

    //         char* tmp = new char [s._capacity + 1] ;

    //         memcpy (tmp , s._str , s._size + 1) ;

    //         delete [] _str ;

    //         _size = s._size ;

    //         _capacity = s._capacity ;

    //     }

    //     return *this ;

    // }

    // 现代写法1: s1 = s2

    // string& string::operator= (const string& s)
    // {

    //     if (this != s)
    //     {

    //         string tmp (s) ;

    //         swap (tmp) ;

    //     }

    //     return *this ;

    // }

    // 现代写法2

    string& string::operator= (string tmp)
    {

        swap (tmp) ;

        return *this ;

    }

    // 下标重载函数

    char& string::operator[] (size_t i)
    {

        assert (i < _size) ; // 检查数组是否越界

        return _str [i] ;

    }

    const char& string::operator[] (size_t i) const
    {

        assert (i < _size) ; // 检查数组是否越界

        return _str [i] ;

    }

    // 由于std库里面的swap函数是浅拷贝函数,所以string类是交换函数需要自己定义

    void string::swap (string& str)
    {

        std::swap (_str , str._str) ;

        std::swap (_size , str._size) ;

        std::swap (_capacity , str._capacity) ;

        // cout << "swap ()" << endl ;

    }


// 查

    const char* string::c_str () const
    {

        return _str ;

    }

    size_t string::size () const
    {

        return _size ;

    }

    size_t string::find (char ch , size_t pos) const
    {

        assert (pos < _size) ;

        for (size_t i = pos ; i < _size ; i++)
        {

            if (_str [i] == ch)
            {

                return i ;

            }
            
        }

        return npos ;
        
    }

    size_t string::find (const char* str , size_t pos) const
    {

        assert (pos < _size) ;

        char* p1 = strstr (_str + pos , str) ;

        if (p1 == nullptr)
        {

            return pos ;

        }

        else
        {

            return p1 - _str ;

        }

    }

    string string::substr (size_t pos , size_t len) const
    {

        assert (pos < _size) ;

        if (len == npos || len >= _size - pos)
        {

            len = _size - pos ;

        }

        string ret ;

        ret.reserve (len) ;

        for (size_t i = 0 ; i < len ; i++)
        {

            ret += _str [pos + i] ;

        }

        return ret ;

    }


// 特殊函数

    // s1 < s2

    // "hello" "hello" -> false

    // "hellox" "hello" -> false

    // "hello" "hellox" -> true

    bool string::operator < (const string& s) const
    {

        size_t s1 = 0 , s2 = 0 ;

        while (s1 < size () && s2 < s.size ())
        {

            if (_str [s1] < s [s2])
            {

                return true ;

            }

            else if (_str [s1] > s [s2])
            {

                return false ;

            }

            else
            {

                s1++ ;

                s2++ ;

            }
            
        }

        return s2 < s.size () ;
        
    }

    bool string::operator <= (const string& s) const
    {

        return *this < s || (*this == s) ;

    }

    bool string::operator > (const string& s) const
    {

        return !(*this <= s) ;
    }

    bool string::operator >= (const string& s) const
    {

        return !(*this < s) ;

    }

    bool string::operator == (const string& s) const
    {

        size_t s1 = 0 , s2 = 0 ;

        while (s1 < _size && s2 < s._size)
        {

            if (_str [s1] != s [s2])
            {

                return false ;

            }

            s1++ ;

            s2++ ;

        }

        return s1 == _size && s2 == s._size ;

    }

    bool string::operator != (const string& s) const
    {

        return !(*this == s) ;

    }
 

// 全局变量定义处

    const size_t string::npos = -1 ; // 这里的npos是静态成员变量,所以要在全局里面声明


// 全局函数定义处

    void swap (string& x , string& y)
    {

        x.swap (y) ;

    }

    ostream& operator << (ostream& out , const string& s)
    {

        // out << c_str () ;

        for (auto ch : s) // 这里使用c_str会出问题,所以使用范围for来打印内容
        {

            out << ch ;

        }

        return out ;

    }

    istream& operator >> (istream& in , string& s)
    {

        s.clear () ;

        char buff [128] ;

        size_t i = 0 ;

        char ch = in.get () ;

        while (ch != ' ' && ch != '\n')
        {

            buff [i++] = ch ;

            if (i == 127)
            {

                buff [i] = '\0' ;

                s += buff ;

                i = 0 ;

            }

            ch = in.get () ;

        }

        if (i > 0)
        {

            buff [i] = '\0' ;

            s += buff ;

        }

        return in ;

    }

    istream& getline (istream& in , string& s , char delim)
    {

        s.clear () ;

        char buff [128] ;

        size_t i = 0 ;

        char ch = in.get () ;

        while (ch != delim)
        {

            buff [i++] = ch ;

            if (i == 127)
            {

                buff [i] = '\0' ;

                s += buff ;

                i = 0 ;

            }

            ch = in.get () ;

        }

        if (i > 0)
        {

            buff [i] = '\0' ;

            s += buff ;
            
        }

        return in ;

    }

}